home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 25
/
Cream of the Crop 25.iso
/
os2
/
srefv12i.zip
/
srefiltr.80
< prev
next >
Wrap
Text File
|
1997-04-18
|
85KB
|
2,392 lines
/* SRE-Filter main program, ver 1.2i
Copyright for the world, Feb 1997, Daniel Hellerstein.
Liability,etc. strictly denied (see the READ.ME file);
but feel free to use and modify this code as you see fit.
*/
/* ---------- User Changeable Parameters -------------
There are several variables set here that you may want to change:
always_check_privs: Flag to "check client privileges even if it's a public url"
BackupServerList: ip addresses of servers to distribute to under load
dir_cache_size: size of the directory-listing cache
dir_cache_duration: lifespan of entries in the directory-listing cache
delay_seconds: time delay for sre-filter to check parameter files for changes
hit_superuser_suppress: modify HIT_OWNER_SUPPRESS to check for SUPERUSERS
ncsa_ismap: substring(s) that signals "this is an NCSA mappable image request"
cern_ismap: substring(s) that signals "this is a CERN mappable image request"
key_preface: optional preface for server side include keywords
logon_limit: maximum # of logon attempts, per minute per client
LoadThreshold: Used with BACKUPSERVERLIST (load at which transfer occurs)
message_scramble: used by messages boxes to encode passwords
no_no_record: Suppress the !NORECORD directive
record_cache_lines: Size of RECORD_ALL_FILE cache
save_state: turn on sre-filter's "save request specific info to file" option
sem_maxwait: waiting time till threads check their queue
ssi_extensions: extensions for which the ssi_shtml_only parameter applies
ssi_cache_size: size of the ssi-cache
ssi_cache_duration: lifespan of entries in the ssi-cache
ssi_cache_stamp: Type of "trigger" check (used with ssi-cache)
See INITFILT.DOC for a discussion of what these do.
Note: The essential difference between parameters here, and in INITFILT.80,
is that these are updated ONLY when GoServe is re-started.
In contrast, INITFILT.80 parameters are checked (and possibly updated)
every "delay_seconds" (default value is 15) seconds.
The notion is that these are more fundamental paramters, which
will need modification less frequently then INITFILT.80 parameters.
------------------ */
/* set to 1 if you want to check for privileges (using inhouseips, owner, additional privileges,
and authorization stuff) when the request string matches a public_URL (set to 0 to NOT check for these privs)
This may "unnecessarily slow things down", but may be required if further privilege checks are
done by sre-filter addons */
always_check_privs=1
/* This spaced delimited list contains ip addresses of backup servers
It's used in conjunction with LOADTHRESHOLD */
BackupServerList = 'www.yahoo.com '
/* set the "duration" of entries in the directory-listing cache.
This is used by the !dir facility of SRE-Filter */
dir_cache_duration=3
/* set the maximum size (in Kbytes) of the directory-listing-cache.
This is used by the !dir facility of sre-filter */
dir_cache_size=1000
/* Delay_seconds controls how frequently sre-filter checks input files
* for updates. Larger values mean more time between checks. */
delay_seconds=15
/* if non-zero, then if hit_owner_suppress is on, also
check if the client has a superuser privilege (that is, if non-0 then
HIT_OWNER_SUPPRESS will treat owners and superusers equivalently)
Note: if HIT_OWNER_SUPPRESS is not enabled, then hit_superuser_suppress
is ignored */
hit_superuser_suppress=1
/* indicators for "mappable image" requests: NSCA and CERN style .MAP files*/
ncsa_ismap='mapimage/ mapnsca/ cgi-bin/mapimage '
cern_ismap='mapcern/ cgi-bin/htimage/'
/* if non-zero, modifies the REPLACE keywords */
key_preface=0 /* key_preface="#" is NOT allowed! */
/* Allow this many simultaneous connections before attempting load balancing
It's used in conjunction with BACKUPSERVERLIST */
LoadThreshold = 0 /* 0 means "do not perform load balancing */
/* sets the maximum number of unsuccessful "logon" attempts, per minute
* per ip address. Set to 0 for "unlimited" attempts.
* Note that a value of 1 may cause problems. */
logon_limit=0
/* this is used to "encrypt" domessage passwords. change it
* for a wee bit extra security */
message_scramble=12415
/* if you want to suppress the use of the !NORECORD directive,
set NO_NO_RECORD=1 */
no_no_record=0
/* this sets the size (in entries_ of the "recordall_file" cache.
* If you do NOT want to cache the recordall_File, set this to 0
* Enabling caching (by using non-0 values0 speeds up throughput,
* but risks minor errors in counts) */
record_cache_lines=0
/* Enable saving of request specific info to a temporary file (for use
by external routines, including SREF_READ_STATE and SREF_WRITE_STATE).
Set to 0 to suppress this, 1 to turn it on */
save_state=0
/* controls "wait on queue" maximum time delay */
sem_maxwait=15000
/* the list of "SSI capable" extensions (used if SSI_SHTML_ONLY='YES') */
ssi_extensions=' SHT SHTML HTML-SSI HTM-SSI '
/* Set the size of the server-side-include (SSI) cache, in kilobytes.
Once cached files (saved to disk) exceed this amount,
older entries will be deleted.
A value of 0 means "do NOT cache".
Example: 1000 means 1M. */
ssi_cache_size=5000
/* set the "lifespan" of ssi-cache entries, in days (fractional values
are allowed). SSI-cache entries older then this will be deleted */
ssi_cache_duration=1
/* set the "type" of trigger checking of ssi-cache entries. You can
the time (TIME), the date (DATE), the time and date (TIMEDATE),
the size (SIZE), or all 3 (ALL). */
ssi_CACHE_stamp='ALL'
/* --------- END OF USER CHANGEABLE SECTION ----------------*/
/* --------- END OF USER CHANGEABLE SECTION ----------------*/
/* --------- END OF USER CHANGEABLE SECTION ----------------*/
/* --------- END OF USER CHANGEABLE SECTION ----------------*/
/* Do NOT change parameters below this line (unless you like to program) */
/*-------------- Load REXX libraries ----- */
/* Load up advanced REXX functions */
foo=rxfuncquery('sysloadfuncs')
if foo=1 then do
call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'
call SysLoadFuncs
end
foo=rxfuncquery('rexxlibregister')
if foo=1 then do
call rxfuncadd 'rexxlibregister','rexxlib', 'rexxlibregister'
call rexxlibregister
end
/* ---------Get stuff sent from GOSERVE program -----------------*/
parse arg source, request , seloriginal
if request=" " then return 'NODATA' /* netscape sometimes does this */
source0=source ; request0=request ; selrec=seloriginal
parse var source myaddr port transaction who whoport . /* Often useful */
parse var request verb uri protocol . /* split up the request line */
enmadd="SREF_"||port||"_"
basesem='\SEM32\'||enmadd
os2e='os2environment'
gospid=dospid()
/* Set: force_auth force_norecord specific_mime del_send */
call modify_seloriginal /* strip out !directives from seloriginal */
if key_preface="#" then key_preface="" /* # not allowed as key_preface */
/* ---- Do we need to initialize sre-filter ? --- */
/* Note: we do not use transaction number, since transaction is NOT reset
when the filter is changed. Hence, the use of this rather convoluted scheme */
thesem=basesem
sem_status=eventsem_query(thesem)
if sem_status<0 then do
servdir=directory() /* should NOT be on-the-fly-changeable */
oo=value(enmadd||'SERVDIR',servdir,'os2environment')
/* to avoid trouble, do not allow any other requests while sre-filter is initializing */
if oo<>"" then do
cl=extract('clients')
if cl=0 then do
call pmprintf(' It appears that the SRE-Filter initialization failed ')
call pmprintf(' Is your net connection working? ')
string ' Sorry: Server Initialization Failure. '
end
else do
call pmprintf(' 2nd request while initializing: deny access for now ')
end
string ' Server is initializing, please try again in a few minutes. '
exit ' '
end
/* first call, start up the helper threads ! */
initfilt_file=servdir||"\INITFILT."||port
aa2=eventsem_close(thesem)
afilt2=servdir'\srefmon.cmd'
moreargs=loadthreshold||','||backupserverlist||','||delay_seconds||','||message_scramble||','||record_cache_lines||','||logon_limit||','||ssi_extensions
moreargs=moreargs||','ssi_cache_size||','||ssi_cache_duration||','||SSI_CACHE_STAMP||','||save_state||','||no_no_record
foo=rexxthread('f',afilt2,gospid,thesem,servdir,PORT,enmadd,sem_maxwait,moreargs)
call pmprintf(' Note: SRE-FILTER monitor started on thread 'foo)
/* allow plenty of time for initialization thread to do it's business */
do forever /* wait for filter monitor to say "go ahead" */
foo=eventsem_wait(thesem,2000)
if foo<>0 then do
call delay(.2)
iterate
end
call pmprintf('SRE-Filter initialization complete ')
leave
end
end /* wait till thesem is set */
/* check if load balancing needed */
if loadthreshold>0 & BackupServerList \= '' then do
'EXTRACT CLIENTS'
if Clients > LoadThreshold then do
foo=completed()
if foo=0 then do
i1=transaction//(words(backupserverlist)+1)
if i1=0 then i1=1
auri=word(backupserverlist,i1)
auri2='http://'||auri||'/'||seloriginal
'HEADER ADD Location:' auri2
'RESPONSE HTTP/1.0 302 Moved Temporarily' /* Set HTTP response line */
'STRING Redirect to backup server at '|| auri
post_filter_message=' Redirected to '||auri
response_status='302 0'
signal do_post_filter
end
end
end /* end of load balancing check */
/* save some request specific variables? */
if save_state=1 then do
verbose=get_value('VERBOSE',0)
tcachfile=sref_save_state(source,request,seloriginal,enmadd,port,verbose)
end
/* check for special message generated by srefquik */
transaction=strip(upper(transaction))
puburl=""
if abbrev(transaction,'PUBFILE_')=1 then do
transaction=delstr(transaction,1,8)
parse var seloriginal puburl seloriginal
selrec=seloriginal
end
if abbrev(transaction,'NOFILE_')=1 then do
transaction=delstr(transaction,1,7)
response_status= not_found_response(seloriginal,' Document not found ',' ')
selrec=' '
post_filter_message="Bad request for public file "
signal do_post_filter
end
/* -----------------Tidy up some initialization parameters ------------ */
skip1: /* if pub_url available, skip here */
privset=' '
owners=' '
current_hit.num=0
current_hit.item=""
current_hit.mess1=""
current_hit.mess2=""
outbig=''
replines.0=-1
interp_data=0
virtual_dir.0=0
cache_status="NOCACHE"
is_public=0
is_alias=0
from_auth=0
post_filter_message=" "
tmp.0=0 /* for use by INTERPRET blocks */
crlf='0d0a'x /* might need this */
nhosts=0
myhost=0
got_def=0
nopostf=' '
do_htaccess=0 /* 0=don't do, 1= do htaccess */
used_file=' ' /* the file this is the target of the request */
gp_param=0 /* getpost optional parameter */
logon_fail_file=0
access_fail_file=0
response_status=' '
serverport=port
internal_procs='SENDFILE SHOWDIR DIR GETAFILE DOSEARCH ASKMESSBOX VIEWMESS GET_URL PUT_FILE MESSAGE '
ncsa_ismap=strip(upper(ncsa_ismap))
cern_ismap=strip(upper(cern_ismap))
clientname0=0
isinhouse=0
mytid=dostid()
mysem=thesem||"t"||mytid
myqueue="SREF_"||port||'_t'||mytid
servdir=value(enmadd||'SERVDIR',,os2e)
nhosts=value(enmadd||'HOSTS.0',,os2e)
no_postfilter=0 ; no_virtual=0
servername=0
/* check on multiple hosts */
if nhosts>0 then do
stuff=sref_host_info(myaddr,nhosts,enmadd)
if stuff<>0 then do
parse var stuff servername ',' host_nickname ',' ddir
host_nickname=strip(host_nickname); ddir=strip(ddir)
default=strip(default) ; servername=strip(servername)
end
end
if servername=0 then do /* nhosts=0, or no match in get_host_info */
ddir=datadir()
servername=servername()
host_nickname=' '
end
/* if !DELSEND special directive, MUST be under tempfile_dir */
if del_send=1 then do
ddir=get_value('TEMPFILE_DIR',0)
end
if ddir="" then do
response_status= not_found_response(seloriginal,' Document not found ',' ')
selrec=' '
post_filter_message="Bad request for public file "
signal do_post_filter
end
verbose=get_value('VERBOSE')
if verbose>3 then say " Using data directory= " ddir seloriginal
if VERBOSE>1 & host_nickname<>' ' then
call pmprintf(' Request to host: ' host_nicknAME)
tempdata_dir=get_value(tempdata_dir)
tdir=strip(TEMPDATA_DIR,'t','\')||'\'
tempfile=tdir'$'transaction'.'port /* Often used */
if stream(tempfile,'c','query exists')<>' ' then do /* just in case of prior crash?*/
say " Warning: old tempfile needs to be removed: " tempfile
tempfile=dostempname(tdir'$??????.'port) /* failure is verrry unlikely! */
end
check_alias=get_value('CHECK_ALIAS')
home_dir=get_value('HOME_DIR')
htaccess_file=get_value('HTACCESS_FILE')
do_htaccess=get_value('DO_HTACCESS')
default=get_value('DEFAULT')
no_include=get_value('NO_INCLUDE')
no_processing=get_value('NO_PROCESSING')
no_interpret_code=get_value('NO_INTERPRET_CODE')
auto_header=get_value('AUTO_HEADER')
home_name=get_value('HOME_NAME')
not_found_url=get_value('NOT_FOUND_URL')
not_found_url=sref_replacestrg(not_found_url,'HOME_NAME',home_name)
/* ---------------------- End of initialization section ------------*/
/* done initializing -- now process the request . */
/* 1) call a pre-filter (it might EXIT back to GoServe)
The pre-filter should check for completion!
Note that pre-filter is ALWAYS called, even if cached transfer occurred*/
pre_filter=get_value('PRE_FILTER')
prefilter_name=get_value('PREFILTER_NAME')
auto_name=get_value('AUTO_NAME')
first_ht_auto=1 /* allow just one auto_name replacement by htaccess */
/* 1a) make personallized queue and semaphore */
call make_semmi
if dienow=0 then return 0 /* error, give up */
/* 1b) if pub_url, then couldn't be a first prefilter, so skip. Otherwise.. */
if pre_filter="FIRST" & puburl="" then do
prefilter_result=do_prefiltr(' ')
parse var prefilter_result status ',' prefilter_result
a=done_it(status,"Pre-filter processed: "||prefilter_result)
if a=1 then do
post_filter_message="Pre-filter used"
signal do_post_filter
end
end
/* 2) MAKE SURE THE REQUEST IS STILL ACTIVE!!
(IF CACHING OCCURED, IT MIGHT NOT BE !! */
aa=done_it(0,'From cache: '||seloriginal)
/* already been completed (possibly from cache) */
if aa=1 then DO
/* a !norecord request */
if force_norecord=1 then return 0
/* is it a public url with NORECORD option */
stuff=sref_public_urls(seloriginal,host_nickname,enmadd,,,,,1)
if stuff=1 then return ' '
/* check access file for nopostfilter */
aline=wait_queue('ACCESS',seloriginal,allow_access)
parse var aline istat ',' accprivs ',' accopts ',' .
if wordpos('NO_POSTFILTER',accopts)>0 then return ' '
/* postfilter not suppressed ... do it */
post_filter_message="Cached file sent:"||seloriginal
response_status='200 '||extract('bytessent')
signal do_post_filter
END
/* 3) Check for basic grooviness */
if left(protocol,4)\='HTTP' & protocol\='' then do
response_status=response('badreq', 'specified a protocol that was not HTTP')
post_filter_message='Bad HTTP Protocol '
signal do_post_filter
end
/* 4) Is it one of the public_urlS ??. IF so, skip logons,
etc (but do aliases and ssi's). */
if puburl<>"" then do /*PUBURL MAYBE SET BY SREFQUIK */
parse var puburl useliteral ',' puburl ; sel=strip(puburl)
if pos('NORECORD',useliteral)>0 then no_postfilter=1 /* LITERALS WILL NEVER MAKE IT HERE */
is_public=1 ; do_htaccess=0
public_privs=get_value('public_privs')
privset=" PUBLICFILE "||PUBLIC_PRIVS
cache_status=' ' /* it's public, so you might as well allow caching */
end
else do
sel=seloriginal
num_pub=get_value("NUM_PUBLIC_URLS")
if num_pub>0 then do
stuff=sref_public_urls(sel,host_nickname,enmadd,ddir,home_dir,verbose,specific_mime)
parse var stuff astat litmatch norecmatch ',' amessage
astat=strip(astat) ; litmatch=strip(litmatch); norecmatch=strip(norecmatch)
/* astat:0=no, 1=yes, litmatch:1=litera, norecmatch:1= norecord */
select
when astat=1 & litmatch<>1 then do
is_public=1 ; do_htaccess=0
if norecmatch=1 then no_postfilter=1
public_privs=get_value('public_privs')
privset=" PUBLICFILE "||PUBLIC_PRIVS
cache_status=' ' /* it's public, so allow caching */
end
when astat=1 & litmatch=1 then do /* sref_public_urls responded to literal puburls */
if norecmatch=1 then return ' '
post_filter_message=strip(amessage)
signal do_post_filter
end
otherwise
nop
end
end /* Num_pub */
end /* puburl */
if is_public=1 then do /* is public url, get privs? */
if always_check_privs=1 then do
if wordpos(who,owners)>0 then privset=privset||" SUPERUSER INHOUSE "||INHOUSE_PRIVS
check_add_privs=get_value('CHECK_ADD_PRIVS') /* LOOK FOR ADDITIONAL PRIVILEGES? */
if check_add_privs=1 then do
aprefix=strip(get_value('ADD_PRIVS_PREFIX'))
ap2=sref_get_add_privs(host_nickname,who,port,enmadd,tempdata_dir,verbose)
ap2=translate(ap2,' ','&') /* correct entry errors (& for RESOURCE privs only */
do iw=1 to words(ap2)
privset=privset||' '||aprefix||strip(word(ap2,iw))
end
end
CALL get_user_privs 0 /* get inhouse, authorization, and own-name privs */
if save_state=1 then foo=sref_write_state('PRIVSET',privset)
end
aline=wait_queue('ACCESS',seloriginal,allow_access) /* get access privileges */
parse var aline . ',' . ',' accopts ',' .
if wordpos('NO_POSTFILTER',upper(accopts))>0 then no_postfilter=1
signal do_alias /* do the verb (skip logons, access check, etc */
end
/* 5) Do we check for logon rights, etc. */
/* 5a) check for bad ip */
username=' ' /* just in case */
owners=get_value('OWNERS')
mdo=sref_badips(who,enmadd,host_nickname)
if mdo=1 then do /* he is a bad ips, but we let owner and inhouse override it */
if wordpos(who,owners)=0 then do /* not an owner */
call goodips(who)
if result=0 then do /* not an inhouseips */
response_status=response('unauth', 'You are not permitted access to this web server ')
post_filter_message="Unauthorized access "
signal do_post_filter
end
else do
if verbose>0 then call pmprintf(' Note: 'who' is a badips and inhouseips -- ignoring badips! ')
username=who
end
end
else do
if verbose>0 then call pmprintf(' Note: 'who' is badips and an owner -- ignoring badips! ')
username='OWNER'
end
end
/* 5b) Do a DNS check ? */
dns_check=get_value('dns_check')
if dns_check="YES" then do
clientname0=clientname()
if clientname0=who then do
audit ' Denied access to ' who
response_status=response('unauth', 'No client name found, access to this web server is denied. ')
post_filter_message="No client name found, access denied "
signal do_post_filter
end
/* say " DNS check ok: " clientname0 */
end
/* 5c) Check user/pwd/privilege list */
checklog=get_value('CHECKLOG')
inhouse_privs=get_value('INHOUSE_PRIVS')
the_realm=get_value('THE_REALM')
allow_access=get_value('ALLOW_ACCESS') ;
cache_status='NOCACHE'
select
when checklog="YES" & (sel=" " ) then do
dologon=1
end
when checklog="INHOUSE" | checklog="ALWAYS" then do
dologon=1
end
otherwise do
dologon=0
if allow_access="YES" | allow_access="YES_NOCHECK" then cache_status=' '
end
end
/* do logons, etc ... */
if wordpos(who,owners)>0 then do /* owners are treated with kid gloves */
privset="SUPERUSER INHOUSE "||inhouse_privs /* also give inhouse privs */
CALL get_user_privs 1,1 /* get user privs */
username="OWNER"
end
else do /* non owners get the third degree? */
if dologon=1 then do /* yup, book 'em */
logon_fail_file=get_value('LOGON_FAIL_FILE')
userinfo=do_logon(who,inhouse_privs) /* if no match, exits (for new pwd or say sorry) */
if gotauser=0 then do
post_filter_message="Logon failed "
response_status=userinfo
signal do_post_filter
end
parse var Userinfo lstat username privset
username=strip(username)
/*very tough--only inhouse allowed (explicit or as a privilege)?*/
if checklog="INHOUSE" & wordpos('INHOUSE',privset)=0 & wordpos('SUPERUSER',privset)=0 then do
response_status=response('unauth', 'Sorry, access currently limited to in-house users ')
post_filter_message="Logon denied to non-inhouse user "
signal do_post_filter
end /* not inhouse */
/* If here, welcome ! */
if verbose>0 then call pmprintf(host_nickname '// 'seloriginal' :request from: ' username '(privs: ' privset)
end /* dologon =1 */
/* If here, then no logons required, */
else do
CALL get_user_privs 1 /* go get inhouse, user; but NOT ownname privileges */
end /* check if logon rwquired */
end /* not superuser */
/* add public_privs to everyone */
public_privs=get_value('public_privs')
privset=privset||' '||public_privs
/* add "username " to privset (this step may be redundant, but... ? */
addname=get_value('add_user_name')
if addname=1 then do
if wordpos(upper(username),upper(privset))=0 then
privset=privset||' '||username
end
/* check for dynamic privileges ? */
check_add_privs=get_value('CHECK_ADD_PRIVS')
if check_add_privs=1 then do
aprefix=strip(get_value('ADD_PRIVS_PREFIX'))
ap2=sref_get_add_privs(host_nickname,who,port,enmadd,tempdata_dir,verbose)
do iw=1 to words(ap2)
privset=privset||' '||aprefix||strip(word(ap2,iw))
end
privset=translate(privset,' ','&') /* correct entry errors */
end
if save_state=1 then foo=sref_write_state('PRIVSET',privset) /* save privset*/
isinhouse=wordpos('INHOUSE',upper(privset)) /* flag for inhouse client */
if wordpos('SUPERUSER',upper(privset))>0 then do
no_processing=0 /* make sure superusrs are unimpeded */
no_interpret_code=0
end
/* 6) now check access file for access and other conditions, for this url. */
aline=wait_queue('ACCESS',seloriginal,allow_access)
parse var aline istat ',' accprivs ',' accopts ',' urlrealm ',' afail_file ',' adv_opts
afail_file=strip(afail_file)
/* Note: access is checked for all request (checked above for public_Urls)
istat=0 for all non-matched urls */
/* should we disallow */
ok1=0
if wordpos('SUPERUSER',privset)>0 then ok1=1
if ok1=0 then do
select
when allow_access="YES" | allow_access="YES_NOCHECK" then
ok1=1
when allow_access="INHOUSE" & isinhouse=1 then
ok1=1
otherwise
if istat<>0 then DO /* if istat=0, then ask_auth below */
/* add own-resource privilege? */
addreso=get_value('ADD_RESOURCE_NAME')
if addreso=1 theN DO
PARSE UPPER VAR SELORIGINAL ACTION '?' .
accprivs=accprivs||' '||action
end
ok1=check_privs(privset,accprivs)
end
end
end
/* if acess to this url not permitted, let client try "another" name,
OR send a response file */
if ok1=0 then do
post_filter_message='Ask Authorization (access file)'
access_fail_file=get_value('ACCESS_FAIL_FILE')
if access_fail_file=0 | force_auth=1 | ,
(access_fail_file<>-1 & reqfield('Authorization')=' ') then do
response_status=ask_auth(the_realm,urlrealm) /* just ask authoriaztion */
end
if afail_file=' ' then afail_file=access_fail_file
awebmaster=get_value('WEBMASTER')
if afail_file=-1 then do /* terse denial */
response_status=response('unauth','Access denied') /* flat out denial */
end
/* possible custom message */
response_status=sref_fail(servername,seloriginal,afail_file,verbose,the_realm,'access failure',awebmaster,'No access privileges to this resource')
signal do_post_filter
end
/* if here, privileges were satisfied */
/* 6a) lookup/set permissions for this url */
/* Now check for ssi and ssp privs */
aok=wordpos('NO_SSI',accopts)
if aok<>0 then
no_include=1
aok=wordpos('NO_SSP',accopts)
if aok<>0 & wordpos('SUPERUSER',privset)=0 then
no_processing=1
aok=wordpos('NO_CODE',accopts)
if aok<>0 & wordpos('SUPERUSER',privset)=0 then
no_interpret_code=1
/* see if this should be cached */
aok=wordpos('CACHE',accopts)
if aok<>0 then
cache_status=' '
/* see if suppress alias and/or suppress of this url*/
if wordpos('NO_ALIAS',accopts)>0 then
check_alias=0
if wordpos('NO_POSTFILTER',accopts)>0 | force_norecord=1 then
no_postfilter=1
if wordpos('NO_VIRTUAL',accopts)>0 then
no_virtual=1
if wordpos('NO_HTACCESS',accopts)>0 then
do_htaccess=0
if wordpos('SUPERUSER',privset)>0 then
do_htaccess=0
if del_send=1 then do /* del_send has limited "mobility" */
cache_status='NOCACHE' ; no_virtual=1 ; check_alias=0
end
/* check on advanced options */
if adv_opts<>" " then do
wd=get_value(workdata_dir)
foo=strip(wd,'t','\')||'\'||strip(adv_opts)
adv_opts_file=stream(foo,'c','query exists')
if adv_opts_file="" then do
say "Warning: missing advanced options file: " adv_opts " ("seloriginal
end
else do
adv_opts=charin(adv_opts_file,1,chars(adv_opts_file))
end
end
/* 7) call prefilter */
/* call a pre-filter (it might EXIT back to GoServe) */
if pre_filter="YES" then do
prefilter_result=do_prefiltr(privset)
parse var prefilter_result status ',' prefilter_result
a=done_it(status,"Pre-filter processed: "||prefilter_result)
if a=1 then do
post_filter_message="Pre-filter used"
signal do_post_filter
end
end
/* 8) do aliases (including blank = default */
if sel=' ' then do
sel=default
selrec='DEFAULT='||sel
got_def=1
end
else do
if substr(sel,1,1)='?' then do /* simple, or with options */
sel=default||sel /* default MUST be an HTML document */
selrec='DEFAULT='||sel
got_def=1
end
end
/* check for redirection default */
if got_def=1 & abbrev(upper(sel),'HTTP://')=1 then do
dog=isa_move(sel,servername,serverport)
if dog<>0 then do
post_filter_message="Alias invoked redirect on default "
signal do_post_filter
end
end
/* Now see if the ACTION is really an alias for some other action */
do_alias: nop /* jump here if is_public */
if check_alias<>0 then do /*see if 'action' is an alias for something else*/
aline=wait_queue('ALIAS',seloriginal)
parse var aline istat newsel
if istat>0 then do
sel=strip(newsel)
if verbose>0 then say " Alias # resolves to: " sel
is_alias=1
end
/* redirection? or absolute file */
if is_alias=1 then do
dog=isa_move(sel,servername,serverport)
if dog<>0 then do
post_filter_message="Alias invoked redirect "
signal do_post_filter
end
/* is this a "send non-data directory file" action
(OBSOLETE, use of virtual directories recommended)*/
if abbrev(upper(sel),"!TRANSFER=") then do
parse var sel action '?' awords
response_status=send_non_datadir(action)
post_filter_message="Transfered non-data directory file: "||awords
signal do_post_filter
end
end
end /* alias checking */
/* 9) See if a "home_dir" flag (a ~) is present. If so, replace it */
parse var sel action '?' awords
foo1=pos('~',action)
if foo1>0 then do /* do ~ for home_dir replacement, with $ option */
action=sref_home_dir(action,home_dir)
action=strip(action,'l','/')
end
if pos('?',sel)>0 then
sel=action||'?'||awords
else
sel=action
/* The next stuff is for GET requests only, so skip otherwise */
if verb<>"GET" | left(sel,1)="!" then signal do_verb
/* 10) Check sel to see if it's a "no extension" variant. If so, NOEXT_TYPE dictates
what to do. */
noexttype=upper(get_value('NOEXT_TYPE'))
if pos("CGI-BIN/",upper(sel))=0 & pos('?',sel)=0 & noexttype<>"NO" then do
if right(sel,1)<>'/' then do /* it doesn't end with a */
foo2=translate(sel,' ','/')
lastword=word(foo2,words(foo2)) /* extract the last piece */
foo2=pos('.',lastword)
if foo2=0 then do /* is no period in the last piece */
sel=fix_url_ext(sel,noexttype)
if sel=-1 then do
post_filter_message=' / added, and redirected: ' sel
signal do_post_filter
end
end
end
end
/* 11) See if we should modify urls of the type /xxx/yyy/ */
sel=strip(sel)
selautoname=sel /* may need to reset sel (see GET verb processing below) */
if pos("CGI-BIN/",upper(sel))>0 | pos('?',sel)>0 | right(sel,1)<>'/' then do
auto_name="" /* never check if a mapimage or cgi-bin call */
first_ht_auto=0
end
else do
first_ht_auto=1
end
goautoname: /* hop here if no match, auto_name <> "" */
if auto_name<>" " & right(sel,1)='/' then do /* some candidate defaults? */
eek=try_auto_name(sel,auto_name)
parse var eek sel auto_name
end /*we may loop here several times, but eventually
the auto_names list will be exhausted */
do_verb: nop /* jump here avoids AUTONAME for POST and HEAD */
/* if adv_ops_file specified, then see if there is an EXEC command(s) in it */
if adv_opts<>' ' then do
tdir=get_value('TEMPFILE_DIR',0)
gotit=sref_adv_opts_exec(adv_opts,source0,request0,seloriginal,privset,verbose, ,
servername,host_nickname,ddir,home_dir,tdir)
if gotit<>0 then do
post_filter_message="Advanced Options completed "
response_status=gotit
signal do_post_filter
end
end
/* ---------- Process a standard (PUT, DELETE, GET,POST, or HEAD) request --------------- */
/* parse ?xx stuff out */
parse var sel action '?' awords
/* .... Now carry out supported verbs (GET POST HEAD POST DELETE ), or SPECIAL control */
/* -- and check for cgi_bin calls -- and check for imagemap calls*/
/* 12a) First, see if it's an imagemap call */
/* is this a mappable image request (note: add .map if necessary)*/
/* note: href="mapimage/bob.map" in url of /work/hi.htm
generates call to url of /work/mapimage/bob.map --
yielding /work/bob.map )
Check the (several) possible NCSA_ISMAP and CERN_ISMAP strings.
*/
if awords<>' ' then do /*possible mapimage call */
jcase=0 ; maptype='NCSA'
uaction=upper(action)
do mm=1 to words(NCSA_ISMAP) /* check ncsa maps */
aw=strip(upper(word(ncsa_ismap,mm)))
if pos(aw,uaction)>0 then do
jcase=4 ; ismap_url=aw
leave
end
end
if jcase=0 then do /*not ncsa, perhaps cern */
do mm=1 to words(CERN_ISMAP)
aw=strip(upper(word(CERN_ismap,mm)))
if pos(aw,uaction)>0 then do
jcase=4 ; maptype='CERN' ; ismap_url=aw
leave
end
end
end /* not ncsa map */
if jcase=4 then do /* process the imagemap -- modify the SEL first */
mapfile0=sref_replacestrg(action,ISMAP_url,"")
mapfile=do_virtual_file(Ddir,MAPFILE0,,,1)
used_file=mapfile
select
when mapfile=0 then
post_filter_message='Mappable image request, file missing:'||mapfile
OTHERWISE DO
MAX_POINTDIST=get_VALUE('MAX_POINTDIST')
FOO=sref_mapimage(mapfile,awords, servername, serverport, ,
tempfile,Ddir, max_pointdist,verbose,mapfile0,maptype)
post_filter_message='Mappable image request:'||foo
RESPONSE_STATUS='302 0'
END
end /*SELECT */
signal do_post_filter
end /*is a mapimage*/
end /* check possible mapinatge */
/* 12b) second, see if cgi-bin call (and cgi-bin emulation is on */
cgi_bin_dir=get_value('CGI_BIN_DIR',0)
tsel=strip(upper(sel))
foobao=pos('CGI-BIN/',tsel)
if (foobao>0) & (cgi_bin_dir<>0) & (verb="GET" | verb="POST") then do
if no_processing=1 then do /* no processing allowed */
response_status=response('unauth',' CGI-BIN processing privileges not granted for: '||sel)
post_filter_message='CGI-BIN processor: not allowed '
fpp=stream(tempfile,'c','close')
signal do_post_filter
end
if foobao=1 then do /* see if alias match */
selt=translate(sel,' ','\/?')
aline=wait_queue('ALIAS',word(selt,2))
parse var aline gotit new_dir
if gotit<>0 & new_dir<> "" then do
cgi_bin_dir=strip(translate(new_dir,'\','/'),'t','\')
end
selcgi=sel
end
else do
cgipath=left(sel,foobao-1)
cgi_bin_dir=do_virtual_file(cgi_bin_dir,cgipath,0,0,1)
selcgi=substr(sel,foobao)
end
temfile_dir=get_value('TEMPDATA_DIR',0)
cmdfile=dostempname(temfile_dir||'\f????.cmd')
filter_name=get_value('FILTER_NAME',0)
if clientname0=0 then
clientname0=clientname()
foox=enmadd' 'transaction' 'home_dir' 'host_nickname
response_status=sref_docgi(cgi_bin_dir, selcgi, verb, clientname0, filter_name, serverport , ,
servername, protocol, ddir, who,tempfile,cmdfile,0,VERBOSE,foox,do_htaccess,htaccess_file,privset)
post_filter_message="CGI-BIN call: "||sel
signal do_post_filter
end /* is a cgi-bin call */
/* 13) third: special requests */
if left(sel,1)='!' then do
usel=upper(sel)
if abbrev(usel,'!DIR')=1 then do
parse var sel action '?' stuff
post_filter_message="!DIR processed "
response_status=sref_dir(ddir,tempfile,action,stuff,tempdata_dir, ,
dir_cache_duration,dir_cache_size,enmadd, ,
transaction,verbose,servername,host_nickname,home_dir)
signal do_post_filter
end
if abbrev(usel,'!SSI')=1 then do
parse var sel action '?' args ; args=strip(args)
if wordpos('SUPERUSER',upper(privset))+wordpos('CONTROL',upper(privset))=0 then do
post_filter_message="!SSI requires authorization "
response_status=ask_auth(the_realm)
end
else do
DIRLIST=SERVDIR||' '||CGI_BIN_DIR||' '||DDIR||' '||HOME_DIR
call check_owner_suppress
foo=sref_do_ssi('*'||strip(args),0,0,0,seloriginal,privset,enmadd, ,
DIRLIST,verbose,transaction,tempfile,key_preface,,
servername||' '||host_nickname,home_name, ,
no_processing||' '||no_interpret_code||' '||force_norecord||' '||is_owner_suppress, ,
myqueue' 'mysem' 'basesem,who)
post_filter_message='SSI processed'
end
signal do_post_filter
end
if abbrev(usel,'!AUTH')=1 then do
post_filter_message='Force_authorization'
response_status=ask_auth(post_filter_message)
signal do_post_filter
end
/* otherwise, one of the generic ones */
post_filter_message=sref_special_request(sel,privset,the_realm,os2e,enmadd,tempfile)
if post_filter_message=-1 then do /* !special requests require special privs */
response_status=ask_auth(the_realm)
end
if abbrev(post_filter_message,'Unknown') then do
response_status=response('badreq', 'asked for unknown Special control "'sel'"')
end
signal do_post_filter
end /* Special ! requests */
/* 14) Fourth: Process the VERB
Currently supported verbs:
HEAD: If auto_header, will also parse html file for header instructions
GET: Several variants: file transfer, file with ssi, ssp
POST: ssp
PUT: write a file (given permission exists)
DELETE: delete a file (given permission exists)
In all cases, the url is mapped to a particular file using the
virtual directory feature (or the data directory if no virtual
directory matches the requested url).
********************/
select
/* 14a) Head Requests */
when verb='HEAD' then do
file=strip(do_virtual_file(ddir,sel))
used_file=file
/* if forbidden, htaccess will EXIT */
if do_htaccess=1 & file<>0 & file<>1 & file<>-1 then do
tmp1=sref_htaccess(seloriginal,file,htaccess_file,who,clientname0, ,
whoport,port,ddir,SERVERNAME,TEMPFILE,0)
if tmp=-1 then do
response_status='401 - '
post_filter_message='Htaccess denial on HEAD '
signal do_post_filter
end
parse var tmp1 foo1 ',' file0 ',' nopostf
file0=strip(file0) ;
if strip(nopostf)=1 then no_postfilter=1
end
select
when file=0 then do
response_status= not_found_response(seloriginal,' Document not found ',' ')
selrec=' '
post_filter_message="HEAD request: Document not found: "||seloriginal
end
otherwise do
post_filter_message="Head request "
if auto_header<>"NO" then do
mtype=mediatype(file)
if mtype="text/html" then do
foo= sref_do_auto_header(file,0) /* sref_do_auto_header will generate the responses */
post_filter_message="Head request with autoheader"
end
end /* AUTOHEADER */
response_status='200 '||dosdir(file,'s')
if adv_opts<>' ' then foo=sref_adv_opts_header(adv_opts,response_status,servername)
'FILE type ' mediatype(file) ' nocache name ' file
response_status='200 '||dosdir(file,'s')
END /*OTHERWISE */
END /* SELECT */
signal do_post_filter
end /* head */
when verb="GET" then do
/* 14b) GET requests ------------------- */
/* There are 4 classes of GET requests supported:
1) Simple file name eg; /ZIPFIP/ZIPFIP.HTM:
file is retrived, with possible ssi's
2) File name with OPTIONS, eg; /OVERVIEW.HTM?From+ZIPFIP+main+page
File is retrieved, with possible ssi's (some of which may use these OPTIONS
3) Form name with parameters, eg; /CALC/DOCALC?12-34%2B51
sref_getpost is called with appropriate arguments
4) Mappable image (ISMAP) response. URL must include the
ncsa_ismap or cern_ismap string (say, MAPIMAGE/) and end with a ?xx,yy.
Eg ISMAPDIR/US/USMAP?41+239
Note: ISINDEX type searchable-index requests are identical in
appearance to case 2. To avoid this problem, use the alias_file
mechanism (described above) to convert to a class 3
( "form name" SEL) that requests DOSEARCH
*/
parse var sel action '?' awords
action=TRANSLATE(strip(action)) /* CAP AND Rid spaces */
if pos('?',sel)=0 then /* no argument list, must be case 1 */
jcase=1
else do /*arguments, class 2,3, or 4 */
attype=mediatype(action)
if attype='text/html' then do /* CLASS 2 ? */
jcase=2 /* class 2: html with "OPTIONS" */
end
else do /* CLASS 3 or 4 */
jcase=3 /* case 3: form */
end
end /* dtermine jcase */
/* Do something (depending on jcase */
if jcase < 3 then do /* genneric file, or html with options */
usef=0 ; c_type=0 ; a_body=0
file=do_virtual_file(ddir,action,,1)
used_file=file
if do_htaccess=1 & file<>1 & file<>-1 then do
tmp1=sref_htaccess(seloriginal,file_nocheck,htaccess_file,who,clientname0, ,
whoport,port,ddir,SERVERNAME,TEMPFILE,0)
if tmp1=-1 then do
response_status='401 - '
post_filter_message='Htaccess denial on GET '
signal do_post_filter
end
parse var tmp1 qca ',' file0 ',' nopostf
file0=strip(file0) ;qca=strip(qca)
if file0<>0 & first_ht_auto=1 then do
auto_name=file0
first_ht_auto=0
end
if qca=0 then cache_status='NOCACHE'
if strip(nopostf)=1 then no_postfilter=1
end
select
when file=0 | file=-1 then DO
if file=-1 | auto_name=" " then do /* no directory specific defaults */
response_status= not_found_response(seloriginal,' Document not found ',not_found_url)
selrec=' '
signal do_post_filter
END
else do /* more directory specific defaults to test? */
sel=selautoname
signal goautoname
END
end
when file=1 then do
usef=1
file=a_body
atype=c_type
end
otherwise
nop
End /* select FILE */
/* File exists! determine mime type */
if usef=1 then
atype=c_type
else
atype=mediatype(action)
/* send a byte range request ? */
if atype<>'text/html' then do
dog=0
if del_send<>1 then dog=process_range(file,atype,usef)
if dog<>0 then do
post_filter_message='Byte ranges in Non-HTML File sent:'||action
RESPONSE_STATUS='206 '||EXTRACT('BYTESSENT')
signal do_post_filter
end
/* IF HERE, not a byte range request */
if usef=0 then do
if del_send=1 then do
response_status='200 '||dosdir(file,'s')
dog='FILE ERASE TYPE '||atype||' NAME '|| file
post_filter_message='Non-HTML File sent & deleted:'||action
end
else do
response_status='200 '||dosdir(file,'s')
dog='FILE TYPE '||atype||" "|| cache_status ||' NAME '|| file
post_filter_message='Non-HTML File sent:'||action
end
fooo=stream(file,'c','close')
if adv_opts<>' ' then foo=sref_adv_opts_header(adv_opts,response_status,servername)
dog
end
else do /* REMOTE FILE SEND */
response_status='200 '||length(a_body)
if adv_opts<>' ' then foo=sref_adv_opts_header(adv_opts,response_status,servername)
'VAR TYPE '|| atype|| ' as '|| ACTION ' NAME a_body '
post_filter_message='Remote Non-HTML File sent:'||action
end
signal do_post_filter
end /* NOT HTML FILE */
/* else,is html, maybe do ssi's?*/
if auto_header="ALWAYS" then
foo= sref_do_auto_header(file,usef) /* sref_do_auto_header will generate EXTRA responses */
call check_owner_suppress
dofile1=do_includes(file,action,awords,usef)
if dofile1=0 then do /* no changes needed (or none attempted), send back requested file */
if usef=1 then do /* FROM REMOTE */
response_status='200 '||length(a_body)
if adv_opts<>' ' then foo=sref_adv_opts_header(adv_opts,response_status,servername)
'VAR TYPE '|| atype|| ' as '|| ACTION ' NAME a_body '
end
else DO /* FROM DISK */
if del_send=1 then do
response_status='200 '||dosdir(file,'s')
dog='FILE ERASE TYPE ' atype ||' NAME '|| file
post_filter_message='HTML File sent & deleted:'||action
end
else do
response_status='200 '||dosdir(file,'s')
dog='FILE TYPE 'atype' ' cache_status ||' NAME '|| file
post_filter_message='HTML File sent:'||action
end
if adv_opts<>' ' then foo=sref_adv_opts_header(adv_opts,response_status,servername)
dog
end
end /* DOFILE1=0 */
else do /* changes were made/results returned, using VAR ,in do_includes */
if dofile1<0 then do
post_filter_message='Problem sending HTML File (with ssi), probably a broken connection:'||action
end
else do
if del_Send=1 & usef<>1 then do
arf=sysfiledelete(file)
post_filter_message='HTML File sent & deleted (with ssi):'||action
end
else do /* STANDARD SSI RETURN -- perhaps from cache */
post_filter_message='HTML File sent (with ssi):'||action
if dofile1<>trunc(dofile1) then
post_filter_message='HTML File sent (from ssi cache):'||action
end
response_status='200 '||trunc(dofile1)
end
end
if usef=1 then post_filter_message=" Remote "||post_filter_message
signal do_post_filter
end /* jcase < 3, file transfer (with includes? */
/* Note on cache_status. If any kind of logon or access control, then
don't cache UNLESS cache specified in access list
Also, if byte range sent, no caching.
and if ssi's happened, no caching.
*/
/* IF HERE, jcase=3, ... it's an action request (i.e.; a FORM response) ... */
/* first, determine if any extra parameters are need, based on ACTION */
if no_processing<>1 then do
usedfile=' '
got1=sref_getpost(tempfile,ACTION,awords,verb,uri,who,servdir,ddir, ,
privset,enmadd,transaction,verbose,serverport,home_dir, ,
servername,host_nickname,do_htaccess,htaccess_file,gp_param||' '||save_state)
pod1=word(got1,1)
if datatype(pod1)="NUM" then do /* it's the response status */
response_status=subword(got1,1,2)
got1=subword(got1,3)
end
POD=LASTPOS(',',GOT1)
IF POD>0 THEN DO
USED_FILE=SUBSTR(GOT1,POD+1)
used_file=strip(used_file)
GOT1=DELSTR(GOT1,POD)
END
used_file=strip(used_file)
post_filter_message=strip(got1)
end
else do
response_status=response('unauth',' Server side processing privileges not granted for: '||action)
post_filter_message='Script processor: not allowed '
end
fpp=stream(tempfile,'c','close')
signal do_post_filter
end /* verb= get */
when verb="POST" Then do
drop awords
'read body var awords' /* get the incoming data */
if rc=-4 then do /* body too large */
response_status= response('badreq', 'sent too much data')
post_filter_message="POST error: too much data"
signal do_post_filter
end
if rc<>0 then do /* e.g., invalid HTTP header */
response_status=response('badreq', 'sent data that could not be read')
post_filter_message="POST error: could not read data ="||rc
signal do_post_filter
end
action=TRANSLATE(strip(sel)) /* CAP AND Rid spaces */
if no_processing<>1 then do
got1=sref_getpost(tempfile,ACTION,awords,verb,uri,who,servdir,ddir, ,
privset,enmadd,transaction,verbose,serverport,home_dir, ,
servername,host_nickname,do_htaccess,htaccess_file,gp_param||' '||save_state)
pod1=word(got1,1)
if datatype(pod1)="NUM" then do /* it's the response status */
response_status=subword(got1,1,2)
got1=subword(got1,3)
end
else do
response_status='201 '||extract('bytessent')
end
POD=LASTPOS(',',GOT1)
IF POD>0 THEN DO
USED_FILE=SUBSTR(GOT1,POD+1)
used_file=strip(used_file)
GOT1=DELSTR(GOT1,POD)
ss=dosdir(used_file,'s')
if ss<>' ' then
RESPONSE_STATUS='201 '||DOSDIR(USED_FILE,'S')
END
used_file=strip(used_file)
post_filter_message=strip(got1)
end
else do
response_status=response('unauth',' Server side processing privileges not granted for: '||action)
post_filter_message='Script processor: not allowed '
end
fpp=stream(tempfile,'c','close')
signal do_post_filter
end
when verb="PUT" then do
parse var sel action '?' .
accept_range=get_value('ACCEPT_RANGE')
aa=sref_do_put('PUT',ddir,sel,enmadd,transaction,accopts, ,
tempfile,home_dir,servername,host_nickname,accept_range,do_htaccess,htaccess_file)
parse var aa aa ',' used_file; aa=strip(aa); used_file=strip(used_file)
post_filter_message='PUT request: '||aa
signal do_post_filter
end
when verb="DELETE" then do
parse var sel action '?' .
accept_range=get_value('ACCEPT_RANGE')
aa=sref_do_put('DELETE',ddir,sel,enmadd,transaction,accopts, ,
tempfile,home_dir,servername,host_nickname,accept_range,do_htaccess,htaccess_file)
parse var aa aa ',' used_file; aa=strip(aa); used_file=strip(used_file)
post_filter_message='DELETE request: '||aa
signal do_post_filter
end
otherwise DO
if VERBOSE>0 then say " no such verb "
RESPONSE_STATUS='501 0'
'NODATA '
END
end /* select verb */
/* jump here after completion code -- do record option and/or post-filter */
do_post_filter:
IF RESPONSE_STATUS=' ' THEN
RESPONSE_STATUS='200 '||EXTRACT('BYTESSENT')
if words(response_status)<2 then do
ofo=extract('bytessent')
response_status=word(response_status,1)||' '||ofo
end
if datatype(strip(word(response_status,2)))<>"NUM" then do
ofo=extract('bytessent')
response_status=word(response_status,1)||' '||ofo
end
/*check for 400 status */
are1=strip(word(response_status,1))
if are1>399 then
record_option='NO'
else
record_option=strip(get_value('RECORD_OPTION'))
if verbose>2 then say " Status message: " post_filter_message
/* check for owner suppression */
call check_owner_suppress
if is_owner_suppress=1 then do
record_option='NO'
if verbose>2 then say " Not recording OWNER or SUPERUSER request "
end
post_filter=strip(get_value('POST_FILTER'))
write_logs=strip(get_value('WRITE_LOGS'))
if (record_option="NO" & post_filter=0 & write_logs=0) | no_postfilter=1 then do /* nothing to do in post filter */
if save_state=1 then foo=sysfiledelete(tcachfile)
return ' '
end
a=rxqueue('s',enmadd||'POSTF')
record_all_file=get_value('RECORD_ALL_FILE',0)
post_filter=get_value('POST_FILTER')
postfilter_name=get_value('POSTFILTER_NAME')
selrec=sref_replacestrg(selrec,',','%2c','ALL')
request0=sref_replacestrg(request0,',','%2c','ALL')
post_filter_message=sref_replacestrg(post_filter_message,',','%2c','ALL')
browser=' ';authuser=' '
thereferer=reqfield('referer')
if write_logs=1 then do
if clientname0=0 then
clientname0=clientname()
browser=reqfield('user-agent')
goo=reqfield('AUTHORIZATION:')
authuser='-'
if goo<>" " then do
parse var goo . m64 . /* get the encoded cookie */
dec=pack64(m64) /* and decode it */
parse upper var dec authuser ':' . /* split to userid */
end
end
fuse=' '
if save_state=1 then do
tdir=strip(TEMPDATA_DIR,'t','\')||'\'
fuse=dostempname(tdir||'_T??????.TMP')
foo2=dosrename(tcachfile,fuse)
if foo2=0 then fuse=' '
end
queue record_option ',' record_all_file ',' post_filter ',' postfilter_name ',' serverport ',' ,
post_filter_message ',' source0 ',' request0 ',' got_def' 'selrec ',' ,
tempfile ',' servername ',' host_nickname ',' used_file ',' who ',' ,
enmadd ',' thereferer ',' fuse ',' RESPONSE_STATUS ',' write_logs ',' ,
clientname0 ',' authuser ',' browser ',' verbose
aa=eventsem_post(basesem||'POSTF')
return ' ' /* note that postfilter and recorder don't need to tell the filter anything*/
/***********/
/* check on owner suppression */
check_owner_suppress:
chkowner=get_value('HIT_OWNER_SUPPRESS')
is_owner_suppress=0
if chkowner=1 then do
if owners=' ' then owners=get_value('Owners')
chkowner2=0
if hit_superuser_suppress=1 then chkowner2=wordpos('SUPERUSER',privset)
if wordpos(who,owners)>0 | chkowner2>0 then do
is_owner_suppress=1
end
end
return is_owner_suppress
/***************/
/* create a personallized queue & semaphore */
make_semmi:
a=rxqueue('s',myqueue)
noq=1
signal on syntax name badq
queue 0
noq=0
badq:
signal off syntax
if noq=1 then do
IF VERBOSE>0 THEN say " creating myqueue " myqueue
foo=rxqueue('c',myqueue)
if upper(foo)<>upper(myqueue) then
say ' wierd queue error ' foo myqueue
a=rxqueue('s',myqueue)
end
yyq=queued()
if yyq>100 then do
if verbose>1 then say " Killing residual queue " myqueue yyq
aa2=rxqueue('d',myqueue)
aa2=rxqueue('c',myqueue)
aa2=rxqueue('s',myqueue)
yyq=queued()
end
do mmy=1 to yyq
pull poo .
end
wow=eventsem_query(mysem)
if wow=-187 then do
a=eventsem_create(mysem)
if a=0 then do
nop
end
else do
call pmprintf(' Could not create semaphore: 'mysem' , error='a)
response_status=response('notfound', ' server is busy, try later')
dienow=0
return 0
end
end
foo=eventsem_reset(MYSEM)
dienow=1
return 1
/* ------------------------------------- */
/* subroutine to strip & set !directives. Sets several globals
so call as routine, not procedure */
modify_seloriginal:
/* special "force authorization" request */
force_auth=0
if abbrev(upper(seloriginal),'!FORCE')=1 then do
seloriginal=substr(seloriginal,8)
selrec=seloriginal
force_auth=1
end
force_norecord=0
if abbrev(upper(seloriginal),'!NORECORD')=1 then do
seloriginal=substr(seloriginal,11)
selrec=seloriginal
if no_no_record<>1 then force_norecord=1
end
specific_mime=0
if abbrev(upper(seloriginal),'!SENDAS_')=1 then do
ooy=pos('/',seloriginal)
ooy2=pos('?',seloriginal)
if ooy2>0 & ooy2< ooy then ooy=ooy2
if ooy>0 then do
specific_mime=substr(seloriginal,9,ooy-9)
seloriginal=substr(seloriginal,ooy+1)
selrec=seloriginal
end
else do
specific_mime=substr(seloriginal,9)
seloriginal=' '
selrec=seloriginal
end
end
del_send=0
if abbrev(upper(seloriginal),'!DELSEND')=1 then do
seloriginal=substr(seloriginal,10)
selrec=seloriginal
del_send=1
end
return
/* ------------------------------------------------ */
/* routine to get privileges (sets privset global). DOES not get public_privs*/
get_user_privs:
parse arg noadd,noinh
privset=privset||' '||check_user_info(who,1,noadd) /* auth, and possibly add-user, privs */
if noinh<>1 then do
call goodips(who) /* is this an inhouse connect - get some privs! */
isin=result
if isin<>0 then privset=PRIVSET||' '||inhouse_privs||' '||privset1
end
RETURN
/******************************************************************************/
/*-- DO_prefiltr: Call User Written pre-filter(s) --**/
/******************************************************************************/
do_prefiltr: procedure expose source0 request0 seloriginal prefilter_name verbose ,
transaction servername host_nickname
parse arg amessage
signal on syntax name bad2a
signal on error name bad2a
foo3=' '
/* note that results from earilier pre-filters are sent do later ones */
do mm=1 to words(prefilter_name)
aname=word(prefilter_name,mm)
yow='foo3='||aname||'(source0,request0,seloriginal,amessage,servername,foo3)'
interpret yow
if completed() then leave /* leave if pre-filter handled the request */
parse var foo3 status ',' prefilter_result
status=strip(status)
if status=1 then leave
end
signal off syntax
signal off error
return foo3
bad2a: /* jump here on syntax error */
signal off syntax
signal off error
call pmprintf(" Error in pre-filter routine " aname)
return amessage
/* ----------------------------------------------------------------------- */
/* Already completed (cache or prefilter. Record it and exit */
/* ----------------------------------------------------------------------- */
done_it: /* need globals, so call as routine */
parse arg status , amessage
issent=0
if datatype(status)<>'NUM' then status=0
if status=0 then issent=completed()
if (issent+status)=0 then return 0 /* otherwise exit */
if VERBOSE>1 then call pmprintf(" Completed or redirected request: " amessage)
parse var sel action '?' awords
return 1
/* ----------------------------------------------------------------------- */
/* RESPONSE: Standard [mostly error] responses.
It calls a macrospace routine that does the work */
/* ----------------------------------------------------------------------- */
response: procedure expose tempfile seloriginal request0 source0 verbose ,
transaction servername host_nickname tempfile
parse arg request, message
foo=sref_response(request,message,tempfile,servername)
return foo
/* ----------------------------------------------------------------------- */
/* NOT_FOUND_RESPONSE: Return "not found" response, use macrospace routine */
/* ----------------------------------------------------------------------- */
not_found_response: procedure expose tempfile verbose transaction servername host_nickname seloriginal a_body
parse arg request, message , message2
a=sref_not_found_response(request, message , message2, tempfile,verbose,transaction,servername,host_nickname,seloriginal)
return a
/* ------------------------------------------------------ */
/* query and wait on helper threads */
/* ------------------------------------------------------*/
wait_queue: procedure expose os2e mysem myqueue enmadd basesem ,
mytid verbose transaction no_virtual servername host_nickname
parse arg athread,args,extra1
athread=strip(athread) ; args=strip(args)
/* check to see if no need to call queue */
a1=check_queue_do(athread,enmadd,args,extra1)
parse var a1 istat ',' ires
if istat=1 then do
ires=strip(ires)
return ires
end
again1t:
goober=enmadd||athread
a=rxqueue('s',goober)
queue transaction ' ' host_nickname ',' myqueue ',' mysem ',' ARGS
a=eventsem_reset(mysem)
dothread=basesem||athread
a=eventsem_post(dothread)
again2t:
a=eventsem_wait(mysem)
if a<>0 then do
call pmprintf(mytid','athread' A Fatal Semaphore failure: 'a)
String 'Web server is temporarily busy '
exit ' '
end
a=rxqueue('s',myqueue)
parse pull aline
PARSE VAR ALINE idnum ',' aline
idnum=strip(translate(idnum,' ','000d0a'x));TRANSACTION=STRIP(TRANSACTION)
if idnum<>transaction then do /*wierd error: got someone else's message! */
say ' Read odd id from queue 'athread ':' transaction ',' idnum
if eventsem_query(mysem)=1 then aa=eventsem_reset(mysem)
signal again2t
end
aline=strip(aline)
return aline
/*-------------------------------------------------*/
/* - Check auto_name list (ONLY called if xxx/yyy/ type of url) ? */
/* ---------------------------------*/
try_auto_name: procedure expose verbose transaction servername host_nickname seloriginal
parse arg sel1,auto_name
lensel1=length(sel1)
tryme=strip(word(auto_name,1))
auto_name=delword(auto_name,1,1) /* remove it from list */
ttryme=upper(tryme)
select
when abbrev(ttryme,"!CREATE")=1 | abbrev(ttryme,'!DIR')=1 then do /* use sref_dir to create a file listing*/
sel1='!dir?/'||sel1
end
when translate(tryme)="!SHOWDIR" then do /* use the builddir ddlp */
sel1='showdir?/'||sel1
END /*SHOWDIR IS A SRE-FILTER FRONT END TO VARIOUS DDLP OF GOHTTP */
when abbrev(tryme,'*')=0 then do
if pos('/',tryme)=1 | pos(':',tryme)>0 then
sel1=tryme
else
sel1=sel1||tryme
end
otherwise do /* *, *.htm, *.html, etc. */
foo2=lastpos('/',sel1,lensel1-1)
parse var tryme ast "." ext
if ext="" then ext="htm"
sel1=sel1||substr(sel1,foo2+1,lensel1-(1+foo2))||'.'||ext
end
end /* select */
if VERBOSE>0 then say "Trying auto-named sel = " sel1
return sel1 auto_name
/***************************************************************************/
/* ---------- ----------------------- ----------*/
/* LOGON checking. If no user match, requery client*/
/* -----------------------------------------------------------------------*/
do_logon: procedure expose inhouseips. enmadd os2e the_realm clientname0 ,
mysem myqueue basesem mytid verbose transaction no_virtual ,
servername host_nickname logon_limit logon_fail_file ,
seloriginal force_auth gotauser tempfile
parse arg anip , inhouse_privs
gotauser=1 /* assume success */
/* see if an inhouseips. */
call goodips(anip)
if result=1 then do
if clientname0=0 then
myname=clientname()
else
myname=clientname0
parse var myname myname1
ptmp=inhouse_privs||' '||privset1
stuff=check_user_info(who)
parse var stuff lstat .
if strip(lstat)>0 then do
parse var stuff uu privset2
ptmp=ptmp||' '||privset2
end
return 1 myname1 ptmp
end
/* not inhouse, check if user info available. */
stuff=check_user_info(anip)
parse var stuff lstat . ; lstat=strip(lstat)
/* valid username? return stuff */
if lstat > 0 then return stuff
/* no such user: either ask again, or send a "failure" response file */
gotauser=0
if logon_fail_file=0 | reqfield('Authorization')=' ' |force_auth=1 then do
return ask_auth(the_realm) /* ask again */
end
/* if here, respond with generic "logon fail file". Note use of amess to
differentiate username failure from logon-limit exceeding */
awebmaster=get_value('WEBMASTER')
if logon_limit >= -lstat | logon_limit=0 then
amess="Incorrect username or password "
else
amess="Too many logon attempts per minute "
return sref_fail(servername,seloriginal,logon_fail_file,verbose,the_realm,'logon failure',awebmaster,amess)
/* ------------------------------------------- */
/* check request header for auth, return user info if found and valid user
if privsonly=1, just return privileges (user specific, and possibly "own name"*/
/* ------------------------------------------- */
check_user_info: procedure expose mysem myqueue basesem enmadd os2e,
mytid verbose transaction no_virtual servername host_nickname
parse arg anip,PRIVSONLY,noadd
FO=0 ; IF PRIVSONLY=1 THEN FO=""
goo=reqfield('AUTHORIZATION:')
if goo=" " then
return FO
parse var goo . m64 . /* get the encoded cookie */
dec=pack64(m64) /* and decode it */
parse upper var dec user ':' pwd /* split to userid and password */
/* get info from user thread */
anarg=User||' '||pwd||' '||anip
stuff=wait_queue('USER',anarg)
parse var stuff astatus privset1
IF verbose>2 THEN SAY " User logon info: " stuff
if noadd<>1 then do
addname=get_value('add_user_name')
if user<>'*' then do
if addname=1 then privset1=privset1||' '||user
end
end
IF PRIVSONLY=1 THEN RETURN PRIVSET1
if astatus>0 then
return 1 user privset1
return astatus
/* -----------------------------------------------------------------------*/
/* see if ip address matches one of a set of good ips (1 if yes)*/
/* check for numeric or names ,and check for wildcards */
/* if non-default host, ONLY get "Host specific" inhouseips */
/* -----------------------------------------------------------------------*/
goodips: procedure expose inhouseips. privset1 enmadd os2e verbose transaction servername host_nickname ,
clientname0
parse arg anips
anips=strip(anips) ;hostn=strip(host_nickname)
if symbol(inhouseips.0)<>"VAR" then do /* not been read yet */
aa='inhouseips.' ;addit=''
if hostN<>"" then addit='.'||hostn
nin=0
do mm=1 to 10000
useme=enmadd||aa||mm||addit ; useme=strip(useme)
tt=strip(value(useme,,os2e))
if tt="" | tt=0 then leave
nin=nin+1 ; inhouseips.nin=upper(tt)
end
inhouseips.0=nin
end
/* check exact matches -- perhaps name matches */
mdo=inhouseips.0
do mm=1 to mdo
if inhouseips.mm=' ' then iterate
if verify(word(inhouseips.mm,1),'*1234567890.')=0 then do /*a numeric ip */
if word(inhouseips.mm,1)=anips then do /*it's an exact match -- extract privset */
parse var inhouseips.mm ff privset1
return 1
end
end
else do /* a name ip */
if clientname0=0 then clientname0=upper(clientname())
if word(inhouseips.mm,1)=clientname0 then do /*it's an exact match -- extract privset */
parse var inhouseips.mm ff privset1
return 1
end
end /* name or number inhouseip */
end
/* if here, try wild card matches */
parse var anips ip.1 '.' ip.2 '.' ip.3 '.' ip.4 .
if clientname0<>0 then
parse var clientname0 cip.1 '.' cip.2 '.' cip.3 '.' cip.4 .
do m2=1 to mdo /* wild card matches */
if inhouseips.m2=' ' then iterate
if pos('*',inhouseips.m2)=0 then iterate
match=1
parse var inhouseips.m2 uip.1 '.' uip.2 '.' uip.3 '.' uip.4 privset1
do mm2 =1 to 4
if uip.mm2="*" then iterate
if uip.mm2=ip.mm2 then iterate
if clientname0<>0 then
if uip.mm2=cip.mm2 then iterate
match=0 /*if here, not a match */
leave
end
if match=1 then return 1
end
return 0 /* no match */
/*--------------------------------------------------*/
/* check user privileges (privset) against a url specific privilege list (aprivs)
if one of them matches, return >0 value
if no match, return 0 */
/* ----------------------------------------------- */
check_privs: procedure expose verbose transaction servername host_nickname ,
who enmadd servdir
parse upper arg privset , aprivs
/* check MUST_HAVE privilegs */
if pos('&',aprivs)>0 then do
musthaves=""
oneofs=""
do jj=1 to words(aprivs) /* extrace MUST_HAVE privs */
ajj=strip(word(aprivs,jj))
if abbrev(ajj,'&')=1 then
musthaves=musthaves||' '||ajj
else
oneofs=oneofs||' '||ajj
end
do jj=1 to words(musthaves)
avi=strip(word(musthaves,jj))
ajj=strip(avi,'l','&')
if wordpos(ajj,privset)=0 then do /* must have ALL must_have privs */
return 0
end
end
aprivs=oneofs
end
/* check ONE_OF privileges */
select
when wordpos('SUPERUSER',privset)>0 then
return 1
when wordpos('NO',aprivs)>0 then do
return 0
end
when aprivs="" | wordpos('*',aprivs)>0 | wordpos('YES',aprivs)>0 then do
return 1
end
otherwise do
do mm=1 to words(aprivs)
if wordpos(word(aprivs,mm),privset)>0 then do
return mm
end
end
end /* otherwise */
end /* select */
return 0
/* -----------------------------------------------------------------------*/
/* Query client for authorization stuff. */
ask_auth:procedure expose verbose transaction servername host_nickname tempfile
PARSE ARG R1, R2
IF R2="" THEN
AREALM=R1
ELSE
AREALM=R2
'header add WWW-Authenticate: Basic Realm=<'||arealm|| '>' /* challenge */
foo=response('unauth', "for realm " arealm " was not authorized")
return foo
/* ----------------------------------------------- */
/* find virtual file name, or perform a remote lookup possibly
returns
file name if local file found
0 if no success in finding local file
If remoteok=1 the ...
-1 if can't get remote file, or not allowed to get it
1 if could get remote file, with info in c_type and a_body exposed variables
if not_f=1, does the "doc not found" to goserv (if 0, does not respond to client)
nocheck=1 -- suppress the nochcek (1= do NOT check for the file's existence) */
/* ----------------------------------------------- */
do_virtual_file:procedure expose os2e mysem myqueue enmadd basesem servername serverport tempfile ,
mytid verbose transaction no_virtual c_type a_body host_nickname file_nocheck
parse arg ddir,sel,not_f,remoteok,nocheck
crlf ='0d0a'x /* constants */
parse var sel action '?' .
file=wait_queue('VIRTUAL',action||' '||ddir)
if abbrev(upper(file),'HTTP:\\')=1 then do
file=translate(file,'/','\')
if remoteok<>1 then return -1 /* do not allow remote "virtual directory*/
tfile=sref_get_remote(file,verbose)
if tfile=0 then do
return -1
end
parse var tfile c_type (crlf) a_body
return 1
end
file_Nocheck=file /* used by htaccess routines */
if nocheck<>1 then do
rf=stream(file,'c','query exists')
if rf="" then do
if not_f<>" " then do
return not_found_response(sel,'Document not found ',not_f)
end
return 0
end
end
return file
/*----------------------------------------------*/
/* fix up extension free url's (after aliasing)
Note that if ?xx appears after a extension-free action (say,
yyy/xxx?abc), then we assume that this is an action request.
Otherwise, depending on value of noexttype
DIR: treat it as a "non-root directory's default document, but they forgot
the final /".
HTM or HTML : Add .HTM or .HTML respectively
NONE : leave it be
*/
fix_url_ext: procedure expose verbose transaction servername host_nickname serverport
parse arg sel, noexttype
select
when noexttype="DIR" then do
sel=sel||'/' /* tIt's a directory*/
if VERBOSE>0 then say " Using DIR re-named Sel: " sel
end
when noexttype="REDIR" then do
sel=sel||'/' /* tIt's a directory*/
foo=isa_move('!MOVED '||sel,servername,serverport)
return -1
end
when noexttype="HTM" then do
sel=sel||".HTM" /* fat style html file */
if VERBOSE>0 then say " Using .HTM re-named Sel: " sel
end
when noexttype="HTML" then do
sel=sel||".HTML" /* html file */
if VERBOSE>0 then say " Using .HTML re-named Sel: " sel
end
when noexttype="NONE" then do
nop /* leave it be */
end
otherwise do
sel=sel||noexttype /* user specified (experimental!) */
if VERBOSE>0 then say " Using other re-named Sel: " sel
end
end /* if select (sel does not end with name.ext) */
return sel
/* -----------------------------------------------------------------------*/
/* check for a "range request". If none found, then return 0.
Else, return an appropriate VAR response, or if multiple
sends, a 1
For details on range retrieval, see draft-ieft-http-range-retrieval-00.txt
(Luotonen and Franks, 2/22/96)
(try ds.internic.net)
*/
/* -----------------------------------------------------------------------*/
process_range: procedure expose enmadd os2e verbose transaction servername host_nickname
parse arg afile,atype,usef
/* do we want to check ranges ? */
accept_range=get_value('ACCEPT_RANGE')
if accept_range<>1 then
return 0
ranges=reqfield('range:')
if ranges="" then do
'HEADER ADD Accept-Ranges: bytes '
return 0
end
/* check for tentative and insertion headers.
i) Unless-modified-since: day, 15 Nov 1995 06:25:55 GMT
ii) If-modified-since: day, 15 Nov 1995 06:25:55 GMT
If exist, compare against date of file.
i) If modified since date, return 0 (that is, treat as a non-range
request
ii) If not modified, return a 304 Not Modified response.
If a If-Valid appears, return 0 (sre-filter does not support If-valid)
If a If-Invalid appears, ignore.
************/
tm1=REQFIELD('If-Valid')
if tm1<>'' then return 0
numeric digits 11
/* files timestamp date */
fildate=dosfileinfo(afile,'W') /* mm/dd/yy hh:mm:ss */
parse var fildate d1 d2
filetime=dateconv(d1,'u','b')+cvt_time_frac(d2)
wow1=reqfield('If-modified-since:')
if wow1<>"" then do
parse var wow1 eek ',' dd mm year atime agmt
asktime=dateconv(dd' 'mm' 'year,'N','B')+cvt_time_frac(atime)
goff=gmtoffset() ; if datatype(goff)<>'NUM' then goff=0
if gmt<>'' then asktime=asktime+ (goff/(24*60*60))
if filetime<asktime then do
'RESPONSE HTTP/1.0 304 Not Modified' /* Set HTTP response line */
'STRING Resource not modified since requested date '
return '304 0'
end
end
wow1=reqfield('Unless-modified-since')
if wow1<>"" then do
parse var wow1 eek ',' dd mm year atime agmt
asktime=dateconv(dd' 'mm' 'year,'N','B')+cvt_time_frac(atime)
goff=gmtoffset() ; if datatype(goff)<>'NUM' then goff=0
if gmt<>'' then asktime=asktime+ (goff/(24*60*60))
if filetime>asktime then return 0 /* modified, better send everything */
end
wow=sref_process_range(afile,atype,ranges,usef)
if wow=0 then do
'HEADER ADD Accept-Ranges: bytes '
end
return wow
/* ** convert hh:mm:ss to fraction of a day */
cvt_time_frac:procedure
parse arg d2
parse var d2 hr ':' min ':' sec
secs=(hr*60*60)+(min*60)+(sec)
fsecs=secs/(24*60*60)
return fsecs
/* ----------------------------------------------------------------------- */
/* SEND_NON_DATADIR -- !TRANSFER -- Send a file not in the data directory
This is basically obsolete, but is retained for occassional use
Use at analias !TRANSFER=X:\DIR\FILE.NAM
*/
/* ----------------------------------------------------------------------- */
send_non_datadir: procedure expose tempfile verbose transaction servername host_nickname ,
specific_mime
parse upper arg taction
taction=strip(taction)
if abbrev(taction,'!TRANSFER=')=1 then
taction=delstr(taction,1,10)
else
return not_found_response(taction,' Could not transfer file ',' ')
action=translate(taction,'\','/')
a=stream(action,'c','query exists')
if a="" then do
return not_found_response(action,' No file to transfer',' ')
end
'FILE TYPE ' mediatype(a) ' nocache NAME' a
return '200 '||dosdir(a,'s')
/* --------------------------------------------------- */
/* take care of server side includes
. If none (or no_include=yes, or is not shtml?), then return 0 -- which means
. "go ahead and return the default document, and maybe cache it? "
*/
/* --------------------------------------------------- */
do_includes:procedure expose tempfile no_include os2e enmadd key_preface,
cgi_bin_dir seloriginal privset servdir verbose transaction ddir ,
home_dir servername host_nickname home_name no_processing myqueue adv_opts,
ssi_extensions who no_interpret_code force_norecord mysem basesem force_auth is_owner_suppress
parse arg tfile,sel0,awords,usef
if no_include=1 then /* don't bother, just return original file */
return 0
ssi_shtml_only=get_value('SSI_SHTML_ONLY')
/* if shtml mode, check if its an .sht[ml] file */
if ssi_shtml_only=1 then do
FOO1=LASTPOS('.',sel0)
if foo1=0 then return 0 /*no extenstion!*/
anext=upper(delstr(sel0,1,foo1))
if wordpos(anext,upper(ssi_extensions))=0 then
return 0
end
if usef<>1 then do
foo=stream(tfile,'c','query exists')
if foo=0 | foo="" then do /*problem opening ! */
if VERBOSE>0 then say " Could not open file for includes : " tfile
return 0 /* just send back file as is */
end
end
/* sref_do_includes */
tmp1=get_value('SSI_CACHE_ON')
ssic=0
if tmp1=0 then ssic=1
if force_auth=1 then ssic=1
DIRLIST=SERVDIR||' '||CGI_BIN_DIR||' '||DDIR||' '||HOME_DIR
gotit=sref_do_ssi(tfile,usef,sel0,awords,seloriginal,privset,enmadd, ,
DIRLIST,verbose,transaction,tempfile,key_preface,,
servername||' '||host_nickname,home_name, ,
no_processing||' '||no_interpret_code||' '||force_norecord||' '||is_owner_suppress,,
myqueue' 'mysem' 'basesem,who,ssic,adv_opts)
return gotit
/**********************************************/
/* check to see if we need NOT call one of the helper threads */
/**********************************************/
check_queue_do:procedure expose no_virtual servername host_nickname
parse arg athread,enmadd,args,allow1
os2e='os2environment'
select
when athread="ALIAS" then do
aaa=get_value('SUPPRESS_ALIAS',0)
if aaa=1 then do
return ' 1 , 0 '|| args
end
end
when athread="USER" then do
if get_value('SUPPRESS_USER',0)=1 then do
yo=get_value('CHECKLOG')
if yo="NO" then
return ' 1 , 1 '
else
return ' 1, 0 '
end
end
when athread="ACCESS" then do
if get_value('SUPPRESS_ACCESS',0)=1 then do
return ' 1 , 0 '
end
if allow1="YES_NOCHECK" then do
return ' 1 , 0 '
end
end
when athread="VIRTUAL" then do
if no_virtual=0 then
no_virtual=get_value('SUPPRESS_VIRTUAL',0)
if no_virtual=1 then do
parse var args action ddir
t1=strip(strip(translate(ddir,'\','/')),,'\')||'\'
action=translate(action,'\','/')
action=strip(action,'l','\')
tryfile=t1||action
return '1 ,'||tryfile
end
end
otherwise DO
return' 0 , 0 '
END
end
RETURN ' 0 ,0'
/* ------------------*/
/* see if this parameter applies to this host */
/* ------------------*/
check_host: procedure
parse upper arg thehost,thearg
f1=strip(word(thearg,1))
if right(f1,2)<>'//' then return thearg /* non host specific */
t1=left(f1,length(f1)-2)
if thehost=t1 then return strip(delword(thearg,1,1)) /* strip host and return */
return ' ' /* 0 signifies don't use */
/* ----------- */
/* get environment value, possibly host specific
hname=0 -- do not look under hostname
hname=1 -- do not look under default
*/
/* ------------ */
get_value: procedure expose enmadd host_nickname
parse upper arg vname,hname0
if hname0=0 then
hname=' '
else
hname=strip(host_nickname)
vname=strip(vname) ;
if hname<>' ' then do
booger=strip(enmadd||vname||'.'||hname)
aval=value(booger,,'os2environment')
if aval<>' ' | hname0=1 Then
return aval
end
aval=value(enmadd||vname,,'os2environment')
return aval
/* --------------------------------- */
/* detect a "moved" url (from an alias) -- calls macrospace routine */
isa_move:procedure expose tempfile verbose servername seloriginal
parse arg sel,servername ,serverport
sel=strip(sel)
tsel=upper(translate(sel,'/','\')) ;a1=left(tsel,1)
if a1='!' | a1='H' then do
wow=sref_isa_move(tsel,sel,servername,serverport,tempfile,verbose,seloriginal)
return wow
end
return 0
/* Determine MIME type. Check the most common ones here,
and if no match, call the more elaboate routine (in macrospace).
This more elaborate one also will examine mediatyp.rxx */
mediatype:procedure expose specific_mime
/* if specific_mime<>0, then use it! */
if specific_mime<>0 then do
aa=translate(specific_mime,' ','_')
m1=strip(word(aa,1)); m2=strip(word(aa,2))
foof=m1||'/'||m2
return foof
end
/* else, use file extension */
parse arg aval
ext=translate(substr(aval, lastpos('.',aval)+1))
if wordpos(ext,'HTM HTML SHTML SHTM HTML-INCLUDE ')>0 then
return ' text/html'
if ext='GIF' then return 'image/gif'
return sref_mediatype(aval)
/* ----------------------------------------------------------------------- */
/* SREF_FAIL: Return a "no acCESS here" response file (and exit)
or returns 0 (caller should do an ask_auth) */
/* ----------------------------------------------------------------------- */
sref_fail:procedure expose the_realm urlrealm
parse arg aserver,AURL,a2,verbose,the_realm,errmess,awebmaster,tellmess
if a2=' ' | a2=1 then return 0
eek=stream(a2,'c','query exists')
if eek<> ' 'then do
atype=sref_mediatype(a2)
if upper(atype)="TEXT/HTML" then do
booger=charin(a2,1,chars(a2))
booger=strip(booger,'t','1a'x)
booger=sref_insert_block(booger,'#URL',aurl,1,'<!--','-->')
alink=' <a href="/!FORCE?'||aurl||'"> Try again? </a>'
booger=sref_insert_block(booger,'#LINK',alink,1,'<!--','-->')
booger=sref_insert_block(booger,'#WEBMASTER',awebmaster,1,'<!--','-->')
booger=sref_insert_block(booger,'#MESSAGE',tellmess,1,'<!--','-->')
a_body=sref_insert_block(booger,'#SERVER',aserver,1,'<!--','-->')
'VAR TYPE '|| atype|| ' as '|| '/'||aurl|| ' NAME a_body '
return '401 '||length(a_body)
end
else do
'FILE TYPE ' atype ' NOCACHE NAME ' a2
return '401 '||dosdir(a2,'s')
end
end
else do
if verbose>0 then say " Warning: Non-existent " errmess " response file:" a2
return ask_auth(the_realm,urlrealm)
end